home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
server
/
init.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
18KB
|
645 lines
/*
* static char *rcsid_init_c =
* "$Id: init.c,v 1.40 1996/07/24 07:38:26 master Exp master $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1992 Mark Wedel
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to master@rahul.net
*/
#include <global.h>
#include <loader.h>
#include <main.h>
#ifndef __CEXTRACT__
#include <sproto.h>
#endif
#include <version.h>
#include <X11/keysym.h>
int init_flag = 0;
int become_daemon = 0;
char *logfilename = LOGFILE;
/*
* init() is called only once, when starting the program.
*/
void init() {
char *di;
init_done=0; /* Must be done before init_signal() */
init_library(); /* Must be called early */
(void) umask(0); /* We don't want to be affected by players' umask */
SRANDOM(time(NULL));
init_startup(); /* Write (C), check shutdown/forbid files */
init_signals(); /* Sets up signal interceptions */
setup_library(); /* Set up callback function pointers */
setuperrors(); /* Sets up X11 error-handlers */
/*init_archetypes(); If not called before, reads all archetypes from file */
/* init_locals();*/ /* Initialize "local" global variables */
init_commands(); /* Sort command tables */
di = (char *) getenv("DISPLAY");
parse_args(di);
#ifdef SOUND_EFFECTS
setup_sounds(); /* Sets up sound effects */
#endif
if((!init_flag)&&di!=NULL&& server_mode != SERVER_ENABLED) {
if(add_player(di,NULL,first_map,0))
LOG(llevError,"%s\n",errmsg);
}
if(first_player==NULL && server_mode != SERVER_ENABLED) {
usage();
exit(1);
}
if (server_mode == SERVER_ENABLED && become_daemon)
logfile = BecomeDaemon(logfilename);
init_ericserver();
init_socket();
reset_sleep();
init_done=1;
}
void usage() {
char *c=strrchr(gargv[0],'/');
(void) fprintf(logfile,
"Usage: %s [-h] [-<flags>]... [display1] [display2]...\n",
(c==NULL?gargv[0]:c+1));
}
void help() {
usage();
printf("Flags:\n");
printf(" -b Black/white instead of colors.\n");
printf(" -d Turns on some debugging.\n");
printf(" -f Only Flush, don't Synchronize.\n");
printf(" This makes the game crash if someone kills their window,\n");
printf(" but the game won't lock if someone freezes it. This speeds\n");
printf(" the game up when there are several players.\n");
printf(" -h Display this information.\n");
printf(" -l Removes local player (Won't try to add player $DISPLAY).\n");
#ifdef DUMP_SWITCHES
printf(" -m Lists out suggested experience for all monsters.\n");
#endif
printf(" -mon Turns on monster debugging.\n");
printf(" -o Prints out info on what was defined at compile time.\n");
printf(" -p Don't try to fix the fontpath.\n");
printf(" -pix Uses pixmaps instead of fonts.\n");
printf(" -s Display the high-score list.\n");
printf(" -v Print version and contributors.\n");
printf(" -w Makes split-windows default.\n");
#ifdef Xpm_Pix
printf(" -xpm Use color pixmaps (XPM) instead of bitmaps or fonts.\n");
#endif
#ifdef CHRFONT
/* Eneq(@csd.uu.se): Added -chrfont <fontname> */
printf(" -chrfont Followed by fontname; will replace character\n");
printf(" rep. by that font.\n");
#endif
#ifdef SERVER
printf(" -server Puts crossfire into server mode.\n");
printf(" -detach The server will go in the background, closing all\n");
printf(" connections to the tty.\n");
printf(" -log <file> Specifies which file to send output to.\n");
printf(" Only has meaning if -detatch is specified.\n");
printf(" -listen_port <port> Specifies server listen port number\n");
#endif
exit(0);
}
void parse_flag(char *flag) {
#ifdef SERVER
if(!strcmp(flag, "-server"))
server_mode = SERVER_ENABLED;
else
#endif
if(!strcmp(flag,"-p"))
fix_fontpath=0;
else if(!strcmp(flag,"-pix"))
use_pixmaps = 1;
else if(!strcmp(flag,"-f"))
synchronize=0;
else if(!strcmp(flag,"-h"))
help();
else if(!strcmp(flag,"-v")) {
version(NULL);
exit(0);
} else if(!strcmp(flag,"-s")) {
display_high_score(NULL,9999);
exit(0);
} else if(!strcmp(flag,"-b"))
no_color=1;
else if(!strcmp(flag,"-l"))
init_flag= -1;
else if(!strcmp(flag,"-d"))
debug = llevDebug;
else if(!strcmp(flag,"-mon"))
debug = llevMonster;
else if(!strcmp(flag,"-o"))
compile_info();
else if(!strcmp(flag,"-w"))
default_split_window=1;
#ifdef DUMP_SWITCHES
else if(!strcmp(flag,"-m"))
dump_monsters=1;
else if(!strcmp(flag,"-m2"))
dump_monsters=2;
else if(!strcmp(flag,"-m3"))
dump_monsters=3;
else if(!strcmp(flag,"-m4"))
dump_monsters=4;
else if(!strcmp(flag,"-m5"))
dump_monsters=5;
else if(!strcmp(flag,"-m6"))
dump_monsters=6;
else if(!strcmp(flag,"-m7"))
dump_monsters=7;
#endif
else if(!strcmp(flag,"-detach"))
become_daemon=1;
else if (!strcmp(flag,"-xpm"))
#if Xpm_Pix
color_pix = 1;
#else
printf("This version was not compiled with color pixmap (XPM) support.\n");
#endif
else if(!strcmp(flag,"-e")) {
fprintf(logfile,
"The editor has been moved into a separate program: crossedit.\n");
exit(0);
} else {
LOG(llevError,"Unknown flag: %s\n",flag);
usage();
exit(-1);
}
}
void parse_args(char *di) {
int i;
for(i=1;i<gargc;i++) {
#ifdef CHRFONT
if (!strncmp(gargv[i], "-chrfont", 8)) {
chrfont=gargv[i+1]; /* Eneq(@csd.uu.se): Handle -chrfont <fontname> */
i++;
} else
#endif
if (!strcmp(gargv[i], "-log")) {
if (++i == gargc) {
fprintf(logfile,"Another argument needed after -log.\n");
exit(-1);
}
logfilename=gargv[i];
#ifdef SERVER
} else if (!strcmp(gargv[i], "-listen_port")) {
extern unsigned short listen_port;
if (++i == gargc) {
fprintf(logfile,"Another argument needed after -listen_port.\n");
exit(-1);
}
listen_port= (unsigned short) atoi(gargv[i]);
if( listen_port<= 0 || listen_port > 32765 || (listen_port<1024 && getuid()!=0)){
fprintf(logfile, "illegal listen_port chosen\n");
listen_port = PORT;
}
} else if (!strcmp(gargv[i],"-eport")) {
extern int eport;
int port;
if (++i == gargc) {
fprintf(logfile,"Another argument needed after -eport.\n");
exit(-1);
}
port= (unsigned short) atoi(gargv[i]);
if( port<= 0 || port > 32765 || (port<1024 && getuid()!=0)){
fprintf(logfile, "illegal eport chosen\n");
}
else eport=port;
#endif
} else
if (gargv[i][0]=='-') {
parse_flag(gargv[i]);
} else {
if(di!=NULL&&!strncmp(gargv[i],di,MAX_NAME))
init_flag=1;
init_beforeplay();
if(add_player(gargv[i],NULL,first_map,0))
LOG(llevDebug,"%s\n",errmsg);
}
}
}
void init_beforeplay() {
init_archetypes(); /* If not called before, reads all archetypes from file */
init_artifacts(); /* If not called before, reads all artifacts from file */
init_spells(); /* If not called before, links archtypes used by spells */
init_archetype_pointers(); /* Setup global pointers to archetypes */
init_races(); /* overwrite race designations using entries in lib/races file */
init_readable(); /* inits useful arrays for readable texts */
#ifdef ALCHEMY
init_formulae(); /* If not called before, reads formulae from file */
#endif
#ifdef ALLOW_SKILLS
init_new_exp_system(); /* If not called before, inits experience system */
#endif
#ifdef DUMP_SWITCHES
switch(dump_monsters) {
case 1:
print_monsters();
exit(0);
case 2:
dump_abilities();
exit(0);
}
#endif
}
void init_startup() {
char buf[MAX_BUF];
FILE *fp;
int comp;
fprintf(logfile,"Welcome to CrossFire, v%s%s\n",VERSION,PATCH);
fprintf(logfile,"Copyright (C) 1994 Mark Wedel.\n");
fprintf(logfile,"Copyright (C) 1992 Frank Tore Johansen.\n");
#ifdef DM_MAIL
fprintf(logfile,"Maintained locally by: %s\n",DM_MAIL);
fprintf(logfile,"Questions and bugs should be mailed to above address.\n");
#endif
#ifdef SHUTDOWN_FILE
sprintf(buf,"%s/%s",LibDir,SHUTDOWN_FILE);
if ((fp = open_and_uncompress(buf, 0, &comp)) != NULL) {
while (fgets(buf, MAX_BUF-1, fp) != NULL)
printf("%s", buf);
close_and_delete(fp, comp);
exit(1);
}
#endif
if (forbid_play()) { /* Maybe showing highscore should be allowed? */
LOG(llevError, "CrossFire: Playing not allowed.\n");
exit(-1);
}
}
/*
* compile_info(): activated with the -o flag.
* It writes out information on how Imakefile and config.h was configured
* at compile time.
*/
void compile_info() {
int i=0;
printf("Non-standard include files:\n");
#if !defined (__STRICT_ANSI__) || defined (__sun__)
#if !defined (Mips)
printf("<stdlib.h>\n");
i=1;
#endif
#if !defined (MACH) && !defined (sony)
printf("<malloc.h>\n");
i=1;
#endif
#endif
#ifndef __STRICT_ANSI__
#ifndef MACH
printf("<memory.h\n");
i=1;
#endif
#endif
#ifndef sgi
printf("<sys/timeb.h>\n");
i=1;
#endif
if(!i)
printf("(none)\n");
#ifdef SECURE
printf("Secure:\t\t<true>\n");
#else
printf("Secure:\t\t<false>\n");
#endif
#ifdef NO_LOG
printf("Logging:\t<false>\n");
#else
printf("Logging:\t<true>\n");
#endif
printf("Libdir:\t\t%s\n",LibDir);
#ifdef PERM_FILE
printf("Perm file:\t<LIB>/%s\n",PERM_FILE);
#endif
#ifdef SHUTDOWN_FILE
printf("Shutdown file:\t<LIB>/%s\n",SHUTDOWN_FILE);
#endif
printf("Save player:\t<true>\n");
printf("Save mode:\t%4.4o\n",SAVE_MODE);
#ifdef SAVE_HOMEDIR
printf("Playerdir:\t%s/%s\n",(char *) getenv("HOME"),PlayerDir);
printf("Save homedir:\t<true>\n");
#else
printf("Playerdir:\t<LIB>/%s\n",PlayerDir);
printf("Save homedir:\t<false>\n");
#endif
#ifdef LOCK_PLAYER
printf("Lock player:\t<true>\n");
#else
printf("Lock player:\t<false>\n");
#endif
#ifdef UNIQUE_ITEMS
printf("Unique items:\t<true>\n");
printf("Itemsdir:\t<LIB>/%s\n", ItemsDir);
#ifdef LOCK_ITEMS
printf("Lock items:\t<true>\n");
#else
printf("Lock items:\t<false>\n");
#endif
#else
printf("Unique items:\t<false>\n");
#endif
#ifdef USE_CHECKSUM
printf("Use checksum:\t<true>\n");
#else
printf("Use checksum:\t<false>\n");
#endif
printf("Tmpdir:\t\t%s\n",TMPDIR);
printf("Fontdir:\t%s\n",FontDir);
printf("Compress:\t%s\n",COMPRESS);
printf("Uncompress:\t%s\n",UNCOMPRESS);
printf("Map max timeout:\t%d\n",MAP_MAXTIMEOUT);
#ifdef MAP_RESET
printf("Map reset:\t<true>\n");
#else
printf("Map reset:\t<false>\n");
#endif
printf("Max objects:\t%d\n",MAX_OBJECTS);
#ifdef USE_CALLOC
printf("Use_calloc:\t<true>\n");
#else
printf("Use_calloc:\t<false>\n");
#endif
#ifdef CHRFONT
printf("CHRFONT:\t<true>\n");
#else
printf("CHRFONT:\t<false>\n");
#endif
#ifdef USE_SWAP_STATS
printf("Use_swap_stats:\t<true>\n");
#else
printf("Use_swap_stats:\t<false>\n");
#endif
#ifdef SOUND_EFFECTS
printf("Sound_effects:\t<true>\n");
#else
printf("Sound_effects:\t<false>\n");
#endif
#ifdef DM_MAIL
printf("DM mail:\t%s\n",DM_MAIL);
#endif
#ifdef X_EDITOR
printf("Editor:\t\t%s\n",X_EDITOR);
#endif
#ifdef SERVER
printf("Server:\t\t<true>\n");
printf("Port:\t\t%d\n",PORT);
#else
printf("Server:\t\t<false>\n");
#endif
#ifdef EXPLORE_MODE
printf("Explore mode:\t<true>\n");
#else
printf("Explore mode:\t<false>\n");
#endif
#ifdef SHOP_LISTINGS
printf("Shop listings:\t<true>\n");
#else
printf("Shop listings:\t<false>\n");
#endif
#ifdef RANDOM_ENCOUNTERS
printf("Random encounter:\t<true>\n");
#else
printf("Random encounter:\t<false>\n");
#endif
#ifdef NEW_IMPROVE_WEAPON
printf("New improve weapon:\t<true>\n");
#else
printf("New improve weapon:\t<false>\n");
#endif
printf("Max_time:\t%d\n",MAX_TIME);
execl("/bin/uname", "uname", "-a", NULL);
LOG(llevError, "Opps, should't have gotten here.");
perror("execl");
exit(-1);
}
/* Signal handlers: */
void rec_sigsegv(int i) {
LOG(llevError,"\nSIGSEGV received.\n");
fatal_signal(1, 1);
}
void rec_sigint(int i) {
LOG(llevError,"\nSIGINT received.\n");
fatal_signal(0, 1);
}
void rec_sighup(int i) {
LOG(llevError,"\nSIGHUP received\n");
fatal_signal(0, 1);
}
void rec_sigquit(int i) {
LOG(llevError,"\nSIGQUIT received\n");
fatal_signal(1, 1);
}
void rec_sigpipe(int i) {
/* Keep running if we receive a sigpipe. Crossfire should really be able
* to handle this signal (at least at some point in the future if not
* right now). By causing a dump right when it is received, it is not
* doing much good. However, if it core dumps later on, at least it can
* be looked at later on, and maybe fix the problem that caused it to
* dump core. There is no reason that SIGPIPES should be fatal
*/
#if 1
LOG(llevError,"\nReceived SIGPIPE, ignoring...\n");
signal(SIGPIPE,rec_sigpipe);/* hocky-pux clears signal handlers */
#else
LOG(llevError,"\nSIGPIPE received, not ignoring...\n");
fatal_signal(1, 1); /*Might consider to uncomment this line */
#endif
}
void rec_sigbus(int i) {
#ifdef SIGBUS
LOG(llevError,"\nSIGBUS received\n");
fatal_signal(1, 1);
#endif
}
void rec_sigterm(int i) {
LOG(llevError,"\nSIGTERM received\n");
fatal_signal(0, 1);
}
void fatal_signal(int make_core, int close_sockets) {
if(init_done) {
emergency_save(0);
clean_tmp_files();
if(close_sockets)
close_all_sockets();
}
if(make_core)
abort();
exit(0);
}
void init_signals() {
signal(SIGHUP,rec_sighup);
signal(SIGINT,rec_sigint);
signal(SIGQUIT,rec_sigquit);
signal(SIGSEGV,rec_sigsegv);
signal(SIGPIPE,rec_sigpipe);
#ifdef SIGBUS
signal(SIGBUS,rec_sigbus);
#endif
signal(SIGTERM,rec_sigterm);
}
/*
* init_library: Set up the function pointers which will point
* back from the library into the server.
*/
void setup_library() {
set_emergency_save(emergency_save);
set_clean_tmp_files(clean_tmp_files);
set_fix_auto_apply(fix_auto_apply);
set_remove_friendly_object(remove_friendly_object);
set_process_active_maps(process_active_maps);
set_update_buttons(update_buttons);
set_draw_info(new_draw_info);
set_draw_stats(draw_stats);
set_draw_inventory(draw_inventory);
set_draw_look(draw_look);
set_apply(apply);
set_draw(draw);
set_monster_check_apply(monster_check_apply);
set_draw_inventory_faces(draw_inventory_faces);
set_draw_look_faces(draw_look_faces);
set_move_teleporter(move_teleporter);
set_move_creator(move_creator);
set_trap_adjust(trap_adjust);
set_esrv_send_item(esrv_send_item);
set_esrv_del_item(esrv_del_item);
/* set_init_blocksview_players(init_blocksview_players);
*/
set_info_map(new_info_map);
}
/* init_races() - reads the races file in the lib/ directory, then
* overwrites old 'race' entries. This routine allow us to quickly
* re-configure the 'alignment' of monsters, objects. Useful for
* putting together lists of creatures, etc that belong to gods.
*/
void init_races () {
FILE *file;
char race[MAX_BUF], fname[MAX_BUF], buf[MAX_BUF], *cp, variable[MAX_BUF];
object *tmp;
int i=-1,j=0,k=0;
archetype *mon=get_archetype_struct();
/* initialize summoned_monsters array, isnt there a better way? */
for(j=0;j<MAX_RACES;j++)
for(k=0;k<MAX_RACE_MEMBERS;k++)
sprintf(summoned_monsters[j][k],"none");
sprintf(race,"none");
sprintf(fname,"%s/%s",LibDir,"races");
if(! (file=fopen(fname,"r")))
{
perror(fname);
return;
}
while(fgets(buf,MAX_BUF,file)!=NULL) {
if(*buf=='#') continue;
if((cp=strchr(buf,'\n'))!=NULL)
*cp='\0';
cp=buf;
while(*cp==' ') /* Skip blanks */
cp++;
if(sscanf(cp,"RACE %s",variable)) { /* set new race value */
j = 0;
i++;
if(i>=MAX_RACES) {
LOG(llevError,"Aborting, need to increase value of MAX_RACES\n");
exit (0);
}
sprintf(race,variable);
sprintf(summoned_monsters[i][j],variable);
} else if(strcmp(race,"none") && sscanf(cp,"%s",variable)) {
/* set creature race to race value */
if((mon=find_archetype(variable))==NULL)
LOG(llevError,"\nCreature %s in race file lacks archetype",variable);
else {
if(mon->clone.race!=NULL) {
LOG(llevDebug,"\n Resetting race to %s from %s for archetype %s",
race,mon->clone.race,mon->name);
free_string(mon->clone.race);
}
mon->clone.race=add_string(race);
/* if the archetype is a monster, add it to the summ monster array */
if(QUERY_FLAG((tmp=arch_to_object(mon)),FLAG_MONSTER)) {
j++;
if(j>=MAX_RACE_MEMBERS) {
LOG(llevError,"Aborting, need to increase value of MAX_RACE_MEMBERS\n");
exit (0);
}
sprintf(summoned_monsters[i][j],variable);
}
free_object(tmp);
}
}
}
#ifdef DUMP_SWITCHES
if (dump_monsters == 6) {
for(i=0;i<MAX_RACES;i++) {
if(strcmp(summoned_monsters[i][0],"none"))
fprintf(stderr,"\nMonsters belonging to race %s:\n",summoned_monsters[i][0]);
else {
fprintf(stderr,"\n");
exit (0);
}
for(j=1;j<MAX_RACE_MEMBERS;j++)
if(strcmp(summoned_monsters[i][j],"none"))
fprintf(stderr," %s",summoned_monsters[i][j]);
}
}
#endif
}